home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / upc12bs1.zip / UUCICO / ulibos2.c < prev    next >
C/C++ Source or Header  |  1993-10-03  |  41KB  |  1,298 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    u l i b o s 2 . c                                               */
  3. /*                                                                    */
  4. /*    OS/2 serial port support for UUCICO                             */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*    Changes Copyright (c) 1989-1993 by Kendra Electronic            */
  9. /*    Wonderworks.                                                    */
  10. /*                                                                    */
  11. /*    All rights reserved except those explicitly granted by the      */
  12. /*    UUPC/extended license agreement.                                */
  13. /*--------------------------------------------------------------------*/
  14.  
  15. /*--------------------------------------------------------------------*/
  16. /*                          RCS Information                           */
  17. /*--------------------------------------------------------------------*/
  18.  
  19. /*
  20.  *       $Id: ulibos2.c 1.23 1993/10/03 22:09:09 ahd Exp $
  21.  *       $Log: ulibos2.c $
  22.  * Revision 1.23  1993/10/03  22:09:09  ahd
  23.  * Use unsigned long to display speed
  24.  *
  25.  * Revision 1.22  1993/10/01  01:17:44  ahd
  26.  * Drop unneeded special case for port in use message
  27.  *
  28.  * Revision 1.21  1993/09/29  05:25:21  ahd
  29.  * Don't die after duplicate port close
  30.  *
  31.  * Revision 1.20  1993/09/29  04:52:03  ahd
  32.  * Use unique handler for port suspending
  33.  *
  34.  * Revision 1.19  1993/09/27  04:04:06  ahd
  35.  * Normalize references to modem speed to avoid incorrect displays
  36.  *
  37.  * Revision 1.18  1993/09/25  03:07:56  ahd
  38.  * Convert to standard OS/2 error message call
  39.  *
  40.  * Revision 1.17  1993/09/24  03:43:27  ahd
  41.  * Use OS/2 error message routine
  42.  *
  43.  * Revision 1.16  1993/09/21  01:42:13  ahd
  44.  * Use standard MAXPACK limit for save buffer size
  45.  *
  46.  * Revision 1.15  1993/09/20  04:46:34  ahd
  47.  * OS/2 2.x support (BC++ 1.0 support)
  48.  * TCP/IP support from Dave Watt
  49.  * 't' protocol support
  50.  *
  51.  * Revision 1.14  1993/05/30  15:25:50  ahd
  52.  * Multiple driver support
  53.  *
  54.  * Revision 1.13  1993/05/30  00:08:03  ahd
  55.  * Multiple communications driver support
  56.  * Delete trace functions
  57.  *
  58.  * Revision 1.12  1993/05/09  03:41:47  ahd
  59.  * Make swrite accept constant input strings
  60.  *
  61.  * Revision 1.11  1993/04/11  00:34:11  ahd
  62.  * Global edits for year, TEXT, etc.
  63.  *
  64.  * Revision 1.10  1993/04/10  21:25:16  dmwatt
  65.  * Add Windows/NT support
  66.  *
  67.  * Revision 1.9  1993/04/05  04:32:19  ahd
  68.  * Additional traps for modem dropping out
  69.  *
  70.  * Revision 1.8  1993/04/04  04:57:01  ahd
  71.  * Add configurable OS/2 priority values
  72.  *
  73.  * Revision 1.7  1992/12/30  13:02:55  dmwatt
  74.  * Dual path for Windows/NT and OS/2
  75.  *
  76.  * Revision 1.6  1992/12/11  12:45:11  ahd
  77.  * Correct RTS handshake
  78.  *
  79.  * Revision 1.5  1992/12/04  01:00:27  ahd
  80.  * Add copyright message, reblock other comments
  81.  *
  82.  * Revision 1.4  1992/11/29  22:09:10  ahd
  83.  * Add new define for BC++ OS/2 build
  84.  *
  85.  * Revision 1.3  1992/11/19  03:00:39  ahd
  86.  * drop rcsid
  87.  *
  88.  * Revision 1.2  1992/11/15  20:11:48  ahd
  89.  * Add English display of modem status and error bits
  90.  *
  91.  */
  92.  
  93. /*--------------------------------------------------------------------*/
  94. /*                        System include files                        */
  95. /*--------------------------------------------------------------------*/
  96.  
  97. #include <stdlib.h>
  98. #include <stdio.h>
  99. #include <string.h>
  100. #include <fcntl.h>
  101. #include <io.h>
  102. #include <time.h>
  103.  
  104. /*--------------------------------------------------------------------*/
  105. /*                         OS/2 include files                         */
  106. /*--------------------------------------------------------------------*/
  107.  
  108. #define INCL_DOSDEVIOCTL
  109. #define INCL_BASE
  110. #define INCL_NOPMAPI
  111.  
  112. #include <os2.h>
  113. #include <limits.h>
  114.  
  115. #ifndef __OS2__
  116. typedef USHORT APIRET ;  // Define older API return type
  117. #endif
  118.  
  119. /*--------------------------------------------------------------------*/
  120. /*                    UUPC/extended include files                     */
  121. /*--------------------------------------------------------------------*/
  122.  
  123. #include "lib.h"
  124. #include "ulib.h"
  125. #include "ssleep.h"
  126. #include "catcher.h"
  127. #include "pos2err.h"
  128.  
  129. #include "commlib.h"
  130. #include "usrcatch.h"
  131.  
  132. /*--------------------------------------------------------------------*/
  133. /*                          Global variables                          */
  134. /*--------------------------------------------------------------------*/
  135.  
  136. currentfile();
  137.  
  138. static boolean   carrierDetect = FALSE;  /* Modem is not connected     */
  139.  
  140. static boolean hangupNeeded = FALSE;
  141.  
  142. static unsigned short currentSpeed = 0;
  143.  
  144. #define FAR_NULL ((PVOID) 0L)
  145.  
  146. /*--------------------------------------------------------------------*/
  147. /*           Definitions of control structures for DOS API            */
  148. /*--------------------------------------------------------------------*/
  149.  
  150. static HFILE com_handle;
  151. static struct _LINECONTROL com_attrib;
  152. static struct _MODEMSTATUS com_signals;
  153. static struct _DCBINFO com_dcbinfo;
  154.  
  155. static void ShowError( const USHORT status );
  156.  
  157. static void ShowModem( const BYTE status );
  158.  
  159. /*--------------------------------------------------------------------*/
  160. /*    n o p e n l i n e                                               */
  161. /*                                                                    */
  162. /*    Open the serial port for I/O                                    */
  163. /*--------------------------------------------------------------------*/
  164.  
  165. int nopenline(char *name, BPS baud, const boolean direct )
  166. {
  167.  
  168.    APIRET rc;
  169.    USHORT com_error;
  170.  
  171. #ifdef __OS2__
  172.    ULONG ParmLengthInOut;
  173.    ULONG DataLengthInOut;
  174.  
  175.    ULONG action;
  176.  
  177. #else
  178.    USHORT action;
  179. #endif
  180.  
  181.    if (portActive)               /* Was the port already active?    */
  182.       closeline();               /* Yes --> Shutdown it before open */
  183.  
  184. #ifdef UDEBUG
  185.    printmsg(15, "nopenline: %s, %lu", name, baud);
  186. #endif
  187.  
  188. /*--------------------------------------------------------------------*/
  189. /*                      Validate the port format                      */
  190. /*--------------------------------------------------------------------*/
  191.  
  192.    if (!equaln(name, "COM", 3 ))
  193.    {
  194.       printmsg(0,"nopenline: Communications port begin with COM, was %s",
  195.          name);
  196.       panic();
  197.    }
  198.  
  199. /*--------------------------------------------------------------------*/
  200. /*                          Perform the open                          */
  201. /*--------------------------------------------------------------------*/
  202.  
  203.    rc = DosOpen( name,
  204.                  &com_handle,
  205.                  &action,
  206.                  0L,
  207.                  0 ,
  208.                  FILE_OPEN ,
  209.                  OPEN_FLAGS_FAIL_ON_ERROR |
  210.                  OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE, 0L );
  211.  
  212. /*--------------------------------------------------------------------*/
  213. /*    Check the open worked.  We translation the common obvious       */
  214. /*    error of file in use to english, for all other errors are we    */
  215. /*    report the raw error code.                                      */
  216. /*--------------------------------------------------------------------*/
  217.  
  218.    if ( rc )
  219.    {
  220.       printOS2error( name, rc );
  221.       return TRUE;
  222.    }
  223.  
  224. /*--------------------------------------------------------------------*/
  225. /*            Reset any errors on the communications port             */
  226. /*--------------------------------------------------------------------*/
  227.  
  228. #ifdef __OS2__
  229.  
  230.    ParmLengthInOut = 0;
  231.    DataLengthInOut = sizeof(com_error);
  232.    rc = DosDevIOCtl( com_handle, IOCTL_ASYNC, ASYNC_GETCOMMERROR,
  233.       NULL,0L,&ParmLengthInOut,(PVOID) &com_error,sizeof(com_error),
  234.       &DataLengthInOut);
  235.  
  236. #else
  237.  
  238.    rc = DosDevIOCtl( &com_error, FAR_NULL, ASYNC_GETCOMMERROR ,
  239.                      IOCTL_ASYNC, com_handle);
  240.  
  241. #endif
  242.  
  243.    if (rc)
  244.    {
  245.       printmsg(0,
  246.             "nopenline: Unable to read errors for %s, error bits %x",
  247.                name, (int) com_error );
  248.       printOS2error( "DosDevIOCtl", rc );
  249.    } /*if */
  250.    else if ( com_error )
  251.       ShowError( com_error );
  252.  
  253. /*--------------------------------------------------------------------*/
  254. /*                           Set baud rate                            */
  255. /*--------------------------------------------------------------------*/
  256.  
  257.    SIOSpeed(baud);
  258.  
  259. /*--------------------------------------------------------------------*/
  260. /*                        Set line attributes                         */
  261. /*--------------------------------------------------------------------*/
  262.  
  263. #ifdef UDEBUG
  264.    printmsg(15,"nopenline: Getting attributes");
  265. #endif
  266.  
  267. #ifdef __OS2__
  268.  
  269.    ParmLengthInOut = 0;
  270.    DataLengthInOut = sizeof(com_attrib);
  271.    rc = DosDevIOCtl( com_handle,
  272.                      IOCTL_ASYNC,
  273.                      ASYNC_GETLINECTRL,
  274.                      NULL,
  275.                      0L,
  276.                      &ParmLengthInOut,
  277.                      (PVOID) &com_attrib,
  278.                      sizeof(com_attrib),
  279.                      &DataLengthInOut); // Get old attributes from device
  280.  
  281. #else
  282.  
  283.    rc = DosDevIOCtl( &com_attrib,
  284.                      FAR_NULL,
  285.                      ASYNC_GETLINECTRL,
  286.                      IOCTL_ASYNC,
  287.                      com_handle);   // Get old attributes from device
  288. #endif
  289.  
  290.    if (rc)
  291.    {
  292.       printmsg(0,"nopenline: Unable to get line attributes for %s",name);
  293.       printOS2error( "DosDevIOCtl", rc );
  294.       panic();
  295.    } /*if */
  296.  
  297.    com_attrib.bDataBits = 0x08; /* Use eight bit path for data      */
  298.    com_attrib.bParity   = 0x00; /* No parity                        */
  299.    com_attrib.bStopBits = 0x00; /* 1 Stop Bit                       */
  300.  
  301. #ifdef UDEBUG
  302.    printmsg(15,"nopenline: Setting attributes");
  303. #endif
  304.  
  305. #ifdef __OS2__
  306.  
  307.    ParmLengthInOut = sizeof(com_attrib);
  308.    DataLengthInOut = 0;
  309.    rc = DosDevIOCtl( com_handle,
  310.                      IOCTL_ASYNC,
  311.                      ASYNC_SETLINECTRL,
  312.                      (PVOID) &com_attrib,
  313.                      sizeof(com_attrib),
  314.                      &ParmLengthInOut,
  315.                      NULL,
  316.                      0L,
  317.                      &DataLengthInOut);
  318.  
  319. #else
  320.  
  321.    rc = DosDevIOCtl( FAR_NULL,
  322.                      &com_attrib,
  323.                      ASYNC_SETLINECTRL,
  324.                      IOCTL_ASYNC,
  325.                      com_handle);
  326. #endif
  327.  
  328.    if (rc)
  329.    {
  330.       printmsg(0,"nopenline: Unable to set line attributes for %s",name);
  331.       printOS2error( "DosDevIOCtl", rc );
  332.       panic();
  333.    } /*if */
  334.  
  335. /*--------------------------------------------------------------------*/
  336. /*       Disable software (XON/XOFF) flow control and enable          */
  337. /*       hardware (CTS) for flow control                              */
  338. /*--------------------------------------------------------------------*/
  339.  
  340. #ifdef UDEBUG
  341.    printmsg(15,"nopenline: Getting flow control information");
  342. #endif
  343.  
  344. #ifdef __OS2__
  345.  
  346.    ParmLengthInOut = 0;
  347.    DataLengthInOut = sizeof(com_dcbinfo);
  348.    rc = DosDevIOCtl( com_handle,
  349.                      IOCTL_ASYNC,
  350.                      ASYNC_GETDCBINFO,
  351.                      NULL,
  352.                      0L,
  353.                      &ParmLengthInOut,
  354.                      (PVOID) &com_dcbinfo,
  355.                      sizeof(com_dcbinfo),
  356.                      &DataLengthInOut);   // Get old attributes from device
  357.  
  358. #else
  359.  
  360.    rc = DosDevIOCtl( &com_dcbinfo,
  361.                      FAR_NULL,
  362.                      ASYNC_GETDCBINFO,
  363.                      IOCTL_ASYNC,
  364.                      com_handle);    // Get old attributes from device
  365.  
  366. #endif
  367.  
  368.    if (rc)
  369.    {
  370.       printmsg(0,"nopenline: Unable to get line attributes for %s",name);
  371.       printOS2error( "DosDevIOCtl", rc );
  372.       panic();
  373.    } /*if */
  374.  
  375.    com_dcbinfo.usWriteTimeout = 2999;  /* Write timeout 30 seconds   */
  376.    com_dcbinfo.usReadTimeout = 24;     /* Read timeout .25 seconds   */
  377.    com_dcbinfo.fbCtlHndShake = (BYTE)
  378.                                (direct ? 0 : MODE_CTS_HANDSHAKE);
  379.    com_dcbinfo.fbFlowReplace = 0;
  380.                                        /* Unless rquested            */
  381.    com_dcbinfo.fbTimeout = MODE_READ_TIMEOUT | MODE_NO_WRITE_TIMEOUT;
  382.  
  383. #ifdef UDEBUG
  384.    printmsg(15,"nopenline: Setting dcb information");
  385. #endif
  386.  
  387. #ifdef __OS2__
  388.  
  389.    ParmLengthInOut = sizeof(com_dcbinfo);
  390.    DataLengthInOut = 0;
  391.    rc = DosDevIOCtl( com_handle,
  392.                      IOCTL_ASYNC,
  393.                      ASYNC_SETDCBINFO,
  394.                      (PVOID) &com_dcbinfo,
  395.                      sizeof(com_dcbinfo),
  396.                      &ParmLengthInOut,
  397.                      NULL,
  398.                      0L,
  399.                      &DataLengthInOut);
  400.  
  401. #else
  402.  
  403.    rc = DosDevIOCtl( FAR_NULL,
  404.                      &com_dcbinfo,
  405.                      ASYNC_SETDCBINFO,
  406.                      IOCTL_ASYNC,
  407.                      com_handle);
  408.  
  409. #endif
  410.  
  411.    if ( rc )
  412.    {
  413.       printmsg(0,"nopenline: Unable to set flow control for %s",name);
  414.       printOS2error( "DosDevIOCtl", rc );
  415.       panic();
  416.    } /*if */
  417.  
  418. /*--------------------------------------------------------------------*/
  419. /*                     Raise Data Terminal Ready                      */
  420. /*--------------------------------------------------------------------*/
  421.  
  422.    com_signals.fbModemOn = DTR_ON | RTS_ON ;
  423.    com_signals.fbModemOff = 0xff;
  424.  
  425. #ifdef UDEBUG
  426.    printmsg(15,"nopenline: Raising RTS/DTR");
  427. #endif
  428.  
  429. #ifdef __OS2__
  430.  
  431.    ParmLengthInOut = sizeof(com_signals);
  432.    DataLengthInOut = sizeof(com_error);
  433.  
  434.    rc = DosDevIOCtl( com_handle,
  435.                      IOCTL_ASYNC,
  436.                      ASYNC_SETMODEMCTRL,
  437.                      (PVOID)&com_signals,
  438.                      sizeof(com_signals),
  439.                      &ParmLengthInOut,
  440.                      (PVOID) &com_error,
  441.                      sizeof(com_error),
  442.                      &DataLengthInOut);
  443.  
  444. #else
  445.  
  446.    rc = DosDevIOCtl( &com_error,
  447.                      &com_signals,
  448.                      ASYNC_SETMODEMCTRL,
  449.                      IOCTL_ASYNC,
  450.                      com_handle);
  451.  
  452. #endif
  453.  
  454.    if (rc)
  455.    {
  456.       printmsg(0,
  457.             "nopenline: Unable to raise DTR/RTS for %s, error bits %#x",
  458.                   name, (int) com_error );
  459.       printOS2error( "DosDevIOCtl", rc );
  460.       panic();
  461.    } /*if */
  462.  
  463.    traceStart( name );     // Enable logging
  464.  
  465.    portActive = TRUE;     /* record status for error handler        */
  466.    carrierDetect = FALSE;  /* Modem is not connected                 */
  467.  
  468. /*--------------------------------------------------------------------*/
  469. /*                     Wait for port to stablize                      */
  470. /*--------------------------------------------------------------------*/
  471.  
  472.    ddelay(500);            /* Allow port to stablize          */
  473.    return 0;
  474.  
  475. } /*nopenline*/
  476.  
  477. /*--------------------------------------------------------------------*/
  478. /*    n s r e a d                                                     */
  479. /*                                                                    */
  480. /*    Read from the serial port                                       */
  481. /*                                                                    */
  482. /*   Non-blocking read essential to "g" protocol.  See "dcpgpkt.c"    */
  483. /*   for description.                                                 */
  484. /*                                                                    */
  485. /*   This all changes in a multi-tasking system.  Requests for I/O    */
  486. /*   should get queued and an event flag given.  Then the             */
  487. /*   requesting process (e.g. gmachine()) waits for the event flag    */
  488. /*   to fire processing either a read or a write.  Could be           */
  489. /*   implemented on VAX/VMS or DG but not MS-DOS.                     */
  490. /*                                                                    */
  491. /*    OS/2 we could multitask, but we just let the system provide     */
  492. /*    a timeout for us with very little CPU usage.                    */
  493. /*--------------------------------------------------------------------*/
  494.  
  495. unsigned int nsread(char *output, unsigned int wanted, unsigned int timeout)
  496. {
  497.    APIRET rc;
  498.    static char save[MAXPACK];
  499.    static USHORT bufsize = 0;
  500.    time_t stop_time ;
  501.    time_t now ;
  502.    USHORT com_error;
  503.  
  504. #ifdef __OS2__
  505.    ULONG ParmLengthInOut;
  506.    ULONG DataLengthInOut;
  507. #endif
  508.  
  509. /*--------------------------------------------------------------------*/
  510. /*           Determine if our internal buffer has the data            */
  511. /*--------------------------------------------------------------------*/
  512.  
  513.    if (bufsize >= wanted)
  514.    {
  515.       memmove( output, save, wanted );
  516.       bufsize -= wanted;
  517.       if ( bufsize )          /* Any data left over?                 */
  518.          memmove( save, &save[wanted], bufsize );  /* Yes --> Save it*/
  519.       return wanted + bufsize;
  520.    } /* if */
  521.  
  522. /*--------------------------------------------------------------------*/
  523. /*            Reset any errors on the communications port             */
  524. /*--------------------------------------------------------------------*/
  525.  
  526. #ifdef __OS2__
  527.  
  528.    ParmLengthInOut = 0;
  529.    DataLengthInOut = sizeof(com_error);
  530.    rc = DosDevIOCtl( com_handle,
  531.                      IOCTL_ASYNC,
  532.                      ASYNC_GETCOMMERROR,
  533.                      NULL,
  534.                      0L,
  535.                      &ParmLengthInOut,
  536.                      (PVOID) &com_error,
  537.                      sizeof(com_error),
  538.                      &DataLengthInOut);
  539.  
  540. #else
  541.  
  542.    rc = DosDevIOCtl( &com_error,
  543.                      FAR_NULL,
  544.                      ASYNC_GETCOMMERROR ,
  545.                      IOCTL_ASYNC,
  546.                      com_handle);
  547.  
  548. #endif
  549.  
  550.    if (rc )
  551.    {
  552.       printmsg(0,"nsread: Unable to read port errors");
  553.       printOS2error( "DosDevIOCtl", rc );
  554.    } /*if */
  555.    else if ( com_error )
  556.       ShowError( com_error );
  557.  
  558. /*--------------------------------------------------------------------*/
  559. /*                 Determine when to stop processing                  */
  560. /*--------------------------------------------------------------------*/
  561.  
  562.    if ( timeout == 0 )
  563.    {
  564.       stop_time = 0;
  565.       now = 1;                /* Any number greater than stop time   */
  566.    }
  567.    else {
  568.       time( & now );
  569.       stop_time = now + timeout;
  570.    }
  571.  
  572. /*--------------------------------------------------------------------*/
  573. /*            Try to read any needed data into the buffer             */
  574. /*--------------------------------------------------------------------*/
  575.  
  576.    do {
  577.       USHORT needed =  (USHORT) wanted - bufsize;
  578.  
  579.       USHORT port_timeout;
  580.  
  581. #ifdef __OS2__
  582.       ULONG received = 0;
  583. #else
  584.       USHORT received = 0;
  585. #endif
  586.  
  587. /*--------------------------------------------------------------------*/
  588. /*                     Handle an aborted program                      */
  589. /*--------------------------------------------------------------------*/
  590.  
  591.       if ( raised )
  592.          return 0;
  593.  
  594.       if ( terminate_processing )
  595.       {
  596.          static boolean recurse = FALSE;
  597.          if ( ! recurse )
  598.          {
  599.             printmsg(2,"nsread: User aborted processing");
  600.             recurse = TRUE;
  601.          }
  602.          return 0;
  603.       }
  604.  
  605. /*--------------------------------------------------------------------*/
  606. /*           Compute a new timeout for the read, if needed            */
  607. /*--------------------------------------------------------------------*/
  608.  
  609.       if (stop_time > now )
  610.       {
  611.          port_timeout = (USHORT) (stop_time - now) / needed * 100;
  612.          if (port_timeout < 100)
  613.             port_timeout = 100;
  614.       }
  615.       else
  616.          port_timeout = 0;
  617.  
  618.       if ( port_timeout != com_dcbinfo.usReadTimeout )
  619.       {
  620.          com_dcbinfo.usReadTimeout = port_timeout;
  621.  
  622. #ifdef __OS2__
  623.  
  624.          ParmLengthInOut = sizeof(com_dcbinfo);
  625.          DataLengthInOut = 0;
  626.          rc = DosDevIOCtl( com_handle,
  627.                            IOCTL_ASYNC,
  628.                            ASYNC_SETDCBINFO,
  629.                            (PVOID) &com_dcbinfo,
  630.                            sizeof(com_dcbinfo),
  631.                            &ParmLengthInOut,
  632.                            NULL,
  633.                            0L,
  634.                            &DataLengthInOut);
  635.  
  636. #else
  637.  
  638.          rc = DosDevIOCtl(FAR_NULL,
  639.                           &com_dcbinfo,
  640.                           ASYNC_SETDCBINFO,
  641.                           IOCTL_ASYNC,
  642.                           com_handle);
  643.  
  644. #endif
  645.          if ( rc )
  646.          {
  647.             printmsg(0,"nsread: Unable to set timeout for comm port");
  648.             printOS2error( "DosDevIOCtl", rc );
  649.             panic();
  650.          } /* if */
  651.       } /* if */
  652.  
  653. #ifdef UDEBUG
  654.       printmsg(15,"nsread: Port time out is %ud seconds/100",
  655.                port_timeout);
  656. #endif
  657.  
  658. /*--------------------------------------------------------------------*/
  659. /*                 Read the data from the serial port                 */
  660. /*--------------------------------------------------------------------*/
  661.  
  662.       rc = DosRead( com_handle, &save[bufsize], needed, &received );
  663.  
  664.       if ( rc == ERROR_INTERRUPT)
  665.       {
  666.          printmsg(2,"Read Interrupted");
  667.          return 0;
  668.       }
  669.       else if ( rc != 0 )
  670.       {
  671.          printmsg(0,"nsread: Read from comm port for %d bytes failed.",
  672.                   needed);
  673.          printOS2error( "DosRead", rc );
  674.          bufsize = 0;
  675.          return 0;
  676.       }
  677.  
  678. #ifdef UDEBUG
  679.       printmsg(15,"nsread: Want %d characters, received %d, total %d in buffer",
  680.             (int) wanted, (int) received, (int) bufsize + received);
  681. #endif
  682.  
  683. /*--------------------------------------------------------------------*/
  684. /*                    Log the newly received data                     */
  685. /*--------------------------------------------------------------------*/
  686.  
  687.       traceData( &save[bufsize], received, FALSE );
  688.  
  689. /*--------------------------------------------------------------------*/
  690. /*            If we got the data, return it to the caller             */
  691. /*--------------------------------------------------------------------*/
  692.  
  693.       bufsize += received;
  694.       if ( bufsize == wanted )
  695.       {
  696.          memmove( output, save, bufsize);
  697.          bufsize = 0;
  698.  
  699.          if (debuglevel > 14)
  700.             fwrite(output,1,bufsize,stdout);
  701.  
  702.          return wanted;
  703.       } /* if */
  704.  
  705. /*--------------------------------------------------------------------*/
  706. /*                 Update the clock for the next pass                 */
  707. /*--------------------------------------------------------------------*/
  708.  
  709.       if (stop_time > 0)
  710.          time( &now );
  711.  
  712.    } while (stop_time > now);
  713.  
  714. /*--------------------------------------------------------------------*/
  715. /*         We don't have enough data; report what we do have          */
  716. /*--------------------------------------------------------------------*/
  717.  
  718.    return bufsize;
  719.  
  720. } /*nsread*/
  721.  
  722. /*--------------------------------------------------------------------*/
  723. /*    n s w r i t e                                                   */
  724. /*                                                                    */
  725. /*    Write to the serial port                                        */
  726. /*--------------------------------------------------------------------*/
  727.  
  728. int nswrite(const char *input, unsigned int len)
  729. {
  730.  
  731.    char *data = (char *) input;
  732.  
  733. #ifdef __OS2__
  734.     ULONG bytes;
  735. #else
  736.    size_t bytes;
  737. #endif
  738.  
  739.    APIRET rc;
  740.  
  741.    hangupNeeded = TRUE;      /* Flag that the port is now dirty  */
  742.  
  743. /*--------------------------------------------------------------------*/
  744. /*         Write the data out as the queue becomes available          */
  745. /*--------------------------------------------------------------------*/
  746.  
  747.    rc = DosWrite( com_handle, data , len, &bytes);
  748.    if (rc)
  749.    {
  750.       printOS2error( "DosWrite", rc );
  751.       return bytes;
  752.    } /*if */
  753.  
  754. /*--------------------------------------------------------------------*/
  755. /*                        Log the data written                        */
  756. /*--------------------------------------------------------------------*/
  757.  
  758.    traceData( data, len, TRUE);
  759.  
  760. /*--------------------------------------------------------------------*/
  761. /*            Return bytes written to the port to the caller          */
  762. /*--------------------------------------------------------------------*/
  763.  
  764.    return len;
  765.  
  766. } /* nswrite */
  767.  
  768. /*--------------------------------------------------------------------*/
  769. /*    n s s e n d b r k                                               */
  770. /*                                                                    */
  771. /*    send a break signal out the serial port                         */
  772. /*--------------------------------------------------------------------*/
  773.  
  774. void nssendbrk(unsigned int duration)
  775. {
  776.  
  777. #ifdef __OS2__
  778.    ULONG ParmLengthInOut;
  779.    ULONG DataLengthInOut;
  780. #endif
  781.  
  782.    USHORT com_error;
  783.  
  784. #ifdef UDEBUG
  785.    printmsg(12, "ssendbrk: %d", duration);
  786. #endif
  787.  
  788. #ifdef __OS2__
  789.  
  790.    ParmLengthInOut = 0;
  791.    DataLengthInOut = sizeof(com_error);
  792.    DosDevIOCtl( com_handle,
  793.                 IOCTL_ASYNC,
  794.                 ASYNC_SETBREAKON,
  795.                 NULL,
  796.                 0L,
  797.                 &ParmLengthInOut,
  798.                 (PVOID) &com_error,
  799.                 sizeof(com_error),
  800.                 &DataLengthInOut);
  801.  
  802. #else
  803.  
  804.    DosDevIOCtl( &com_error,
  805.                 FAR_NULL,
  806.                 ASYNC_SETBREAKON,
  807.                 IOCTL_ASYNC,
  808.                 com_handle);
  809.  
  810. #endif
  811.  
  812.    if ( com_error )
  813.       ShowError( com_error );
  814.  
  815.    ddelay( duration == 0 ? 200 : duration);
  816.  
  817. #ifdef __OS2__
  818.    ParmLengthInOut = 0;
  819.    DataLengthInOut = sizeof(com_error);
  820.    DosDevIOCtl( com_handle,
  821.                 IOCTL_ASYNC,
  822.                 ASYNC_SETBREAKOFF,
  823.                 NULL,
  824.                 0L,
  825.                 &ParmLengthInOut,
  826.                 (PVOID) &com_error,
  827.                 sizeof(com_error),
  828.                 &DataLengthInOut);
  829.  
  830. #else
  831.    DosDevIOCtl( &com_error,
  832.                 FAR_NULL,
  833.                 ASYNC_SETBREAKOFF,
  834.                 IOCTL_ASYNC,
  835.                 com_handle);
  836. #endif
  837.  
  838.    if ( com_error )
  839.       ShowError( com_error );
  840.  
  841. } /*nssendbrk*/
  842.  
  843. /*--------------------------------------------------------------------*/
  844. /*    n c l o s e l i n e                                             */
  845. /*                                                                    */
  846. /*    Close the serial port down                                      */
  847. /*--------------------------------------------------------------------*/
  848.  
  849. void ncloseline(void)
  850. {
  851.    APIRET rc;
  852.    USHORT com_error;
  853.  
  854. #ifdef __OS2__
  855.    ULONG ParmLengthInOut;
  856.    ULONG DataLengthInOut;
  857. #endif
  858.  
  859.  
  860.    if ( ! portActive )
  861.    {
  862.       printmsg(0,"ncloseline: Internal error, port already closed");
  863.       return;
  864.    }
  865.  
  866.    portActive = FALSE; /* flag port closed for error handler  */
  867.    hangupNeeded = FALSE;  /* Don't fiddle with port any more  */
  868.  
  869. /*--------------------------------------------------------------------*/
  870. /*                             Lower DTR                              */
  871. /*--------------------------------------------------------------------*/
  872.  
  873.    com_signals.fbModemOn  = 0x00;
  874.    com_signals.fbModemOff = DTR_OFF | RTS_OFF;
  875.  
  876. #ifdef __OS2__
  877.  
  878.    ParmLengthInOut = sizeof(com_signals);
  879.    DataLengthInOut = sizeof(com_error);
  880.  
  881.    rc = DosDevIOCtl( com_handle,
  882.                      IOCTL_ASYNC,
  883.                      ASYNC_SETMODEMCTRL,
  884.                      (PVOID)&com_signals,
  885.                      sizeof(com_signals),
  886.                      &ParmLengthInOut,
  887.                      (PVOID) &com_error,
  888.                      sizeof(com_error),
  889.                      &DataLengthInOut);
  890.  
  891. #else
  892.  
  893.    rc = DosDevIOCtl( &com_error,
  894.                      &com_signals,
  895.                      ASYNC_SETMODEMCTRL,
  896.                      IOCTL_ASYNC,
  897.                      com_handle);
  898.  
  899. #endif
  900.  
  901.    if ( rc )
  902.    {
  903.       printmsg(0,"ncloseline: Unable to lower DTR/RTS for port");
  904.       printOS2error( "DosDevIOCtl", rc );
  905.    }
  906.    else if ( com_error )
  907.          ShowError( com_error );
  908.  
  909. /*--------------------------------------------------------------------*/
  910. /*                      Actually close the port                       */
  911. /*--------------------------------------------------------------------*/
  912.  
  913.    rc = DosClose( com_handle );
  914.  
  915.    if ( rc != 0 )
  916.       printOS2error( "DosClose", rc );
  917.  
  918. /*--------------------------------------------------------------------*/
  919. /*                   Stop logging the data to disk                    */
  920. /*--------------------------------------------------------------------*/
  921.  
  922.    traceStop();
  923.  
  924. } /* ncloseline */
  925.  
  926. /*--------------------------------------------------------------------*/
  927. /*    n h a n g u p                                                   */
  928. /*                                                                    */
  929. /*    Hangup the telephone by dropping DTR.  Works with HAYES and     */
  930. /*    many compatibles.                                               */
  931. /*    14 May 89 Drew Derbyshire                                       */
  932. /*--------------------------------------------------------------------*/
  933.  
  934. void nhangup( void )
  935. {
  936.  
  937. #ifdef __OS2__
  938.    ULONG ParmLengthInOut;
  939.    ULONG DataLengthInOut;
  940. #endif
  941.  
  942.    USHORT com_error;
  943.    APIRET rc;
  944.  
  945.    if (!hangupNeeded)
  946.       return;
  947.  
  948.    hangupNeeded = FALSE;
  949.  
  950. /*--------------------------------------------------------------------*/
  951. /*                              Drop DTR                              */
  952. /*--------------------------------------------------------------------*/
  953.  
  954.    com_signals.fbModemOn  = 0x00;
  955.    com_signals.fbModemOff = DTR_OFF;
  956.  
  957. #ifdef __OS2__
  958.  
  959.    ParmLengthInOut = sizeof(com_signals);
  960.    DataLengthInOut = sizeof(com_error);
  961.  
  962.    rc = DosDevIOCtl( com_handle,
  963.                      IOCTL_ASYNC,
  964.                      ASYNC_SETMODEMCTRL,
  965.                      (PVOID)&com_signals,
  966.                      sizeof(com_signals),
  967.                      &ParmLengthInOut,
  968.                      (PVOID) &com_error,
  969.                      sizeof(com_error),
  970.                      &DataLengthInOut);
  971.  
  972. #else
  973.  
  974.    rc = DosDevIOCtl( &com_error,
  975.                      &com_signals,
  976.                      ASYNC_SETMODEMCTRL,
  977.                      IOCTL_ASYNC,
  978.                      com_handle);
  979.  
  980. #endif
  981.  
  982.    if ( rc )
  983.    {
  984.       printmsg(0,"hangup: Unable to lower DTR for comm port");
  985.       printOS2error( "DosDevIOCtl", rc );
  986.    } /*if */
  987.    else if ( com_error )
  988.          ShowError( com_error );
  989.  
  990. /*--------------------------------------------------------------------*/
  991. /*                  Wait for the telephone to hangup                  */
  992. /*--------------------------------------------------------------------*/
  993.  
  994.    printmsg(3,"hangup: Dropped DTR");
  995.    carrierDetect = FALSE;  /* Modem is not connected                 */
  996.    ddelay(500);            /* Really only need 250 milliseconds         */
  997.  
  998. /*--------------------------------------------------------------------*/
  999. /*                          Bring DTR back up                         */
  1000. /*--------------------------------------------------------------------*/
  1001.  
  1002.    com_signals.fbModemOn = DTR_ON;
  1003.    com_signals.fbModemOff = 0xff;
  1004.  
  1005. #ifdef __OS2__
  1006.  
  1007.    ParmLengthInOut = sizeof(com_signals);
  1008.    DataLengthInOut = sizeof(com_error);
  1009.  
  1010.    rc = DosDevIOCtl( com_handle,
  1011.                      IOCTL_ASYNC, ASYNC_SETMODEMCTRL,
  1012.                      (PVOID)&com_signals,
  1013.                      sizeof(com_signals),
  1014.                      &ParmLengthInOut,
  1015.                      (PVOID) &com_error,
  1016.                      sizeof(com_error),
  1017.                      &DataLengthInOut);
  1018.  
  1019. #else
  1020.  
  1021.    rc = DosDevIOCtl( &com_error,
  1022.                      &com_signals,
  1023.                      ASYNC_SETMODEMCTRL,
  1024.                      IOCTL_ASYNC,
  1025.                      com_handle);
  1026.  
  1027. #endif
  1028.  
  1029.    if ( rc )
  1030.    {
  1031.       printmsg(0,"hangup: Unable to raise DTR for comm port");
  1032.       printOS2error( "DosDevIOCtl", rc );
  1033.    } /*if */
  1034.    else if ( com_error )
  1035.          ShowError( com_error );
  1036.  
  1037.    ddelay(2000);           /* Now wait for the poor thing to recover    */
  1038.  
  1039. } /* nhangup */
  1040.  
  1041. /*--------------------------------------------------------------------*/
  1042. /*    n S I O S p e e d                                               */
  1043. /*                                                                    */
  1044. /*    Re-specify the speed of an opened serial port                   */
  1045. /*                                                                    */
  1046. /*    Dropped the DTR off/on calls because this makes a Hayes drop    */
  1047. /*    the line if configured properly, and we don't want the modem    */
  1048. /*    to drop the phone on the floor if we are performing             */
  1049. /*    autobaud.                                                       */
  1050. /*                                                                    */
  1051. /*    (Configured properly = standard method of making a Hayes        */
  1052. /*    hang up the telephone, especially when you can't get it into    */
  1053. /*    command state because it is at the wrong speed or whatever.)    */
  1054. /*--------------------------------------------------------------------*/
  1055.  
  1056. void nSIOSpeed(BPS baud)
  1057. {
  1058.    APIRET rc;
  1059.  
  1060. #ifdef __OS2__
  1061.  
  1062.    ULONG ParmLengthInOut;
  1063.    ULONG DataLengthInOut;
  1064.  
  1065.    struct
  1066.    {
  1067.       ULONG baud;       // this structure is needed to set the extended
  1068.       BYTE fraction;    // baud rate using function 41h DosDevIOCtl
  1069.    } com_baud;
  1070.  
  1071. #else
  1072.  
  1073.    USHORT speed = (USHORT) baud;
  1074.  
  1075. #endif
  1076.  
  1077. #ifdef UDEBUG
  1078.    printmsg(15,"SIOSpeed: Setting baud rate to %lu",
  1079.                (unsigned long) baud);
  1080. #endif
  1081.  
  1082. #ifdef __OS2__
  1083.  
  1084. /*--------------------------------------------------------------------*/
  1085. /*       OS/2 2.x Format of call for DosDevIOCtl accepts baud         */
  1086. /*       rates greater than 19200.                                    */
  1087. /*--------------------------------------------------------------------*/
  1088.  
  1089.    com_baud.baud = baud;
  1090.    com_baud.fraction = 0;
  1091.    ParmLengthInOut = sizeof(com_baud);
  1092.    DataLengthInOut = 0;
  1093.  
  1094.    rc = DosDevIOCtl( com_handle,
  1095.                     IOCTL_ASYNC,
  1096.                     ASYNC_SETBAUDRATE,
  1097.                     (PVOID) &com_baud,
  1098.                     sizeof(com_baud),
  1099.                     &ParmLengthInOut,
  1100.                     NULL,
  1101.                     0L,
  1102.                     &DataLengthInOut);
  1103.  
  1104. #else
  1105.    rc = DosDevIOCtl( FAR_NULL,
  1106.                      &speed,
  1107.                      ASYNC_SETBAUDRATE,
  1108.                      IOCTL_ASYNC,
  1109.                      com_handle);
  1110. #endif
  1111.  
  1112.    if (rc)
  1113.    {
  1114.       printmsg(0,"SIOSPeed: Unable to set baud rate for port to %lu",
  1115.                baud);
  1116.       printOS2error( "DosDevIOCtl", rc );
  1117.       panic();
  1118.    } /*if */
  1119.  
  1120.    currentSpeed = (unsigned short) baud;
  1121.  
  1122. } /* nSIOSpeed */
  1123.  
  1124. /*--------------------------------------------------------------------*/
  1125. /*    n f l o w c o n t r o l                                         */
  1126. /*                                                                    */
  1127. /*    Enable/Disable in band (XON/XOFF) flow control                  */
  1128. /*--------------------------------------------------------------------*/
  1129.  
  1130. void nflowcontrol( boolean flow )
  1131. {
  1132.    APIRET rc;
  1133.  
  1134. #ifdef __OS2__
  1135.    ULONG ParmLengthInOut;
  1136.    ULONG DataLengthInOut;
  1137. #endif
  1138.  
  1139.    if ( flow )
  1140.        com_dcbinfo.fbFlowReplace = (char)
  1141.             (com_dcbinfo.fbFlowReplace |
  1142.             (MODE_AUTO_TRANSMIT | MODE_AUTO_RECEIVE));
  1143.    else
  1144.       com_dcbinfo.fbFlowReplace = (char)
  1145.             (com_dcbinfo.fbFlowReplace &
  1146.             (0xff - MODE_AUTO_TRANSMIT - MODE_AUTO_RECEIVE));
  1147.  
  1148. #ifdef __OS2__
  1149.  
  1150.    ParmLengthInOut = sizeof(com_dcbinfo);
  1151.    DataLengthInOut = 0;
  1152.    rc = DosDevIOCtl( com_handle,
  1153.                      IOCTL_ASYNC,
  1154.                      ASYNC_SETDCBINFO,
  1155.                      (PVOID) &com_dcbinfo,
  1156.                      sizeof(com_dcbinfo),
  1157.                      &ParmLengthInOut,
  1158.                      NULL,
  1159.                      0L,
  1160.                      &DataLengthInOut);
  1161.  
  1162. #else
  1163.  
  1164.    rc = DosDevIOCtl( FAR_NULL,
  1165.                      &com_dcbinfo,
  1166.                      ASYNC_SETDCBINFO,
  1167.                      IOCTL_ASYNC,
  1168.                      com_handle);
  1169.  
  1170. #endif
  1171.  
  1172.    if ( rc )
  1173.    {
  1174.       printmsg(0,"flowcontrol: Unable to set flow control");
  1175.       printOS2error( "DosDevIOCtl", rc );
  1176.       panic();
  1177.    } /*if */
  1178.  
  1179. } /* nflowcontrol */
  1180.  
  1181. /*--------------------------------------------------------------------*/
  1182. /*    n G e t S p e e d                                               */
  1183. /*                                                                    */
  1184. /*    Report current speed of communications connection               */
  1185. /*--------------------------------------------------------------------*/
  1186.  
  1187. BPS nGetSpeed( void )
  1188. {
  1189.    return currentSpeed;
  1190. } /* nGetSpeed */
  1191.  
  1192. /*--------------------------------------------------------------------*/
  1193. /*   n C D                                                            */
  1194. /*                                                                    */
  1195. /*   Return status of carrier detect                                  */
  1196. /*--------------------------------------------------------------------*/
  1197.  
  1198. boolean nCD( void )
  1199. {
  1200.    boolean previousCarrierDetect = carrierDetect;
  1201.    APIRET rc;
  1202.  
  1203. #ifdef __OS2__
  1204.    ULONG ParmLengthInOut;
  1205.    ULONG DataLengthInOut;
  1206. #endif
  1207.  
  1208.    BYTE status;
  1209.    static BYTE oldstatus = (BYTE) 0xDEAD;
  1210.  
  1211. #ifdef __OS2__
  1212.    ParmLengthInOut = 0;
  1213.    DataLengthInOut = sizeof(status);
  1214.    rc = DosDevIOCtl( com_handle,
  1215.                      IOCTL_ASYNC,
  1216.                      ASYNC_GETMODEMINPUT,
  1217.                      NULL,
  1218.                      0L,
  1219.                      &ParmLengthInOut,
  1220.                      (PVOID) &status,
  1221.                      sizeof(status),
  1222.                      &DataLengthInOut);
  1223. #else
  1224.  
  1225.    rc = DosDevIOCtl( &status,
  1226.                      0L,
  1227.                      ASYNC_GETMODEMINPUT,
  1228.                      IOCTL_ASYNC,
  1229.                      com_handle );
  1230.  
  1231. #endif
  1232.  
  1233.    if ( rc )
  1234.    {
  1235.       printmsg(0,"CD: Unable to get modem status");
  1236.       printOS2error( "DosDevIOCtl", rc );
  1237.    } /*if */
  1238.  
  1239.    if ( status != oldstatus )
  1240.    {
  1241.       ShowModem( status );
  1242.       oldstatus = status;
  1243.    }
  1244.  
  1245. /*--------------------------------------------------------------------*/
  1246. /*    If we previously had carrier detect but have lost it, we        */
  1247. /*    report it was lost.  If we do not yet have carrier detect,      */
  1248. /*    we return success because we may not have connected yet.        */
  1249. /*--------------------------------------------------------------------*/
  1250.  
  1251.    carrierDetect = status && DCD_ON;
  1252.  
  1253.    if (previousCarrierDetect)
  1254.       return carrierDetect;
  1255.    else
  1256.       return (status && DSR_ON);
  1257.  
  1258. } /* nCD */
  1259.  
  1260. /*--------------------------------------------------------------------*/
  1261. /*    S h o w M o d e m                                               */
  1262. /*                                                                    */
  1263. /*    Report current modem status                                     */
  1264. /*--------------------------------------------------------------------*/
  1265.  
  1266. #define mannounce(flag, bits, text ) ((flag & bits) ? text : "" )
  1267.  
  1268. static void ShowModem( const BYTE status )
  1269. {
  1270.    if ( debuglevel < 4 )
  1271.       return;
  1272.  
  1273.    printmsg(0, "ShowModem: %#02x%s%s%s%s",
  1274.       (int) status,
  1275.       mannounce(DCD_ON,   status, "  Carrier Detect"),
  1276.       mannounce(RI_ON,    status, "  Ring Indicator"),
  1277.       mannounce(DSR_ON,   status, "  Data Set Ready"),
  1278.       mannounce(CTS_ON,   status, "  Clear to Send"));
  1279.  
  1280. } /* ShowModem */
  1281.  
  1282. /*--------------------------------------------------------------------*/
  1283. /*    S h o w E r r o r                                               */
  1284. /*                                                                    */
  1285. /*    Report modem error bits in English (more or less)               */
  1286. /*--------------------------------------------------------------------*/
  1287.  
  1288. static void ShowError( const USHORT status )
  1289. {
  1290.    printmsg(2, "Port Error: %#04x%s%s%s%s",
  1291.       (int) status,
  1292.       mannounce(RX_QUE_OVERRUN,      status, "  Queue Overrrun"),
  1293.       mannounce(RX_HARDWARE_OVERRUN, status, "  Hardware Overrun"),
  1294.       mannounce(PARITY_ERROR,        status, "  Parity Error"),
  1295.       mannounce(FRAMING_ERROR,       status, "  Framing Error"));
  1296.  
  1297. } /* ShowError */
  1298.